<template>
    <el-popover :teleported="false" :placement="placement" :width="popoverWidth" :visible="visible">  
        <template #reference>
            <div :class="['stage-subject','sss', ssClass]" @click="toggle" ref="inputStageWrapper">
                <div class="ss">
                    <template v-if="isHasData">
                        <div class="ss-stage"
                            v-for="(item, stageIndex) in stateData.resultToSubmit"
                            :key="item[optionsData.stageId]">
                            <div class="ss-stagename ss-bold">{{ item[optionsData.stageName] + '：'}}</div>
                            <div class="ss-stageback">
                                <div class="ss-back" v-if="item.subjectList && item.subjectList.length">
                                    <div class="ss-stagename" v-if="props.isShowGrade">学科：</div>
                                    <div class="ss-subjects">
                                        <span class="ss-subject"
                                            v-for="(subject, subjectIndex) in item.subjectList"
                                            :key="subject[optionsData.subjectId]">
                                            {{ subject[optionsData.subjectName] }}
                                            <i class="stage-icon-guanbi"
                                                @click.stop="delSubject(stageIndex, subjectIndex, item[optionsData.stageId], subject[optionsData.subjectId])"></i>
                                        </span>
                                    </div>
                                </div>
                                <div class="ss-back" v-if="props.isShowGrade && item.gradeList && item.gradeList.length">
                                    <div class="ss-stagename">年级：</div>
                                    <div class="ss-subjects">
                                        <span class="ss-subject"
                                            v-for="(subject, subjectIndex) in item.gradeList"
                                            :key="subject[optionsData.gradeId]">
                                            {{ subject[optionsData.gradeName] }}
                                            <i class="stage-icon-guanbi"
                                                @click.stop="delGrade(stageIndex, subjectIndex, item[optionsData.stageId], subject[optionsData.gradeId])"></i>
                                        </span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </template>
                    <div class="placeholder"
                        v-else>{{ props.placeholder }}</div>
                </div>
                <i class="stage-icon-clear" v-if="stateData.resultToSubmit.length" @click.stop="resetCommit"></i>
            </div>
        </template>
            <div ref="selectStageWrapper" class="stage-subject-container">
                <div class="sss-list-inner">
                    <!-- 左边部分所有学段数据 -->
                    <div class="stages" :style="{height: props.height ? `${props.height}px` : 'auto'}">
                        <div :class="['stage', fmtStageClass(item.stage)]"
                            v-for="item in stateData.stages"
                            :key="item.stage"
                            @click="checkStage(item)">
                            <div class="stage-name">
                                {{item.stageName}}
                            </div>
                            <div class="selected-num"
                                v-if="stateData.stageNumMap[item.stage] && fmtNum(stateData.stageNumMap[item.stage])">{{ fmtNum(stateData.stageNumMap[item.stage]) }}</div>
                        </div>
                    </div>
                     <!-- 右边部分学段对应的学科、年级数据 -->
                    <div class="subjects" :style="{height: props.height ? `${props.height}px` : 'auto'}">
                        <div class="subject">
                            <el-checkbox v-model="isAllCheckedSubject"
                                @change="selectAll($event, 'subjectNum')">全学科</el-checkbox>
                        </div>
                        <div class="subjects-inner">
                            <div class="subject"
                                v-for="subject in stateData.stageSubjectMap[curStage]"
                                :key="`${curStage}-${subject.code}`">
                                <el-checkbox v-model="subject.checked" 
                                    @change="changeChecked($event, subject, 'subjectNum')">{{ subject.name }}</el-checkbox>
                            </div>
                        </div>
                        <!-- 右边部分学段对应的年级数据 -->
                        <template v-if="props.isShowGrade">
                            <div class="subject mtop" v-if="stateData.stageGradeMap[curStage] && stateData.stageGradeMap[curStage].length">
                                <el-checkbox v-model="isAllCheckedGrade"
                                    @change="selectAll($event, 'gradeNum')">全年级</el-checkbox>
                            </div>
                            <div class="subjects-inner">
                                <div class="subject"
                                    v-for="grade in stateData.stageGradeMap[curStage]"
                                    :key="`${curStage}-${grade.code}`">
                                    <el-checkbox v-model="grade.checked" 
                                        @change="changeChecked($event, grade, 'gradeNum')">{{ grade.name }}</el-checkbox>
                                </div>
                            </div>
                        </template>
                    </div>
                </div>
                <div class="btns">
                    <div class="btn btn-reset"
                        @click="toggle">取消</div>
                    <div class="btn btn-confirm"
                        @click="confirm">确定</div>
                </div>
            </div>
    </el-popover>
</template>

<script setup>
import { onMounted, ref, reactive, nextTick, computed, unref, onBeforeUnmount, defineEmits, defineProps, watch } from 'vue'
import { useStore } from 'vuex';
import { deepCopy } from '@/lib/tools';


const store = useStore();

// update:selectedData 格式与props的selectedData格式一致
const emit = defineEmits(['update:selectedData']);

const visible = ref(false);

const isInit = ref(true);// 是否是初始化进来

// 输入框
const inputStageWrapper = ref(null);

// 下拉内容
const selectStageWrapper = ref(null);


const props = defineProps({
    placeholder: {
        type: String,
        default: '请选择学段学科年级'
    },
    selectedData: {// 回显数据
        type: Array,
        default: () => {
            return []
            // return [{
            //     stageId: 1202,
            //     stageName: '小学',
            //     subjectList: [
            //         {
            //             'subjectId': 1197,
            //             'subjectName': '劳动'
            //         }
            //     ],
            //     gradeList: [
            //          {
            //             'gradeId': 1301,
            //             'gradeName': '一年级'
            //         } 
            //     ]
            // }]
        }
    },
    options: {// 自定义回显对象属性
        type: Object,
        default: () => {
            return {
                stageId: 'stageId',
                stageName: 'stageName',
                subjectId: 'subjectId',
                subjectName: 'subjectName',
                gradeId: 'gradeId',
                gradeName: 'gradeName'
            }
        }
    },
    isShowGrade: { // 是否显示年级
        type: Boolean,
        default: true
    },
    list: { // 学段学科初始化数据
        type: Array,
        default: () => {
            return []
        }
    },
    placement: { // 出现的位置
        type: String,
        default: 'bottom'
    },
    // 级联框高度
    height: {
        type: [String, Number],
        default: ''
    }
})

// 自定义属性
const optionsData = computed(() => {
    return Object.assign({}, {
        stageId: 'stageId',
        stageName: 'stageName',
        subjectId: 'subjectId',
        subjectName: 'subjectName',
        gradeId: 'gradeId',
        gradeName: 'gradeName'
    }, props.options);
})



const data = ref({}); // 下拉需要渲染数据

const curStage = ref('')// 下拉激活的学段

const popoverWidth = ref(600);// 默认的宽度

const stateData = reactive({
    basicData: [], // 接口返回的初始数据
    stages: [], // 所有学段数据-排序
    stageNameMap: {}, // 所有学段对象数据
    resultToSubmit: [], // 文本框需要提交的数据
    commitResult: [], // 组装好的需要提交的数据
    initSelectData: [], // 初始化的选中数据
    stageSubjectMap: {}, // 学段学科数据
    stageGradeMap: {}, // 学段年级数据
    stageNumMap: {} // 学段对应的选中的学科年级数据  subjectNum + gradeNum
  
})

// 样式
const ssClass = computed(() => {
    return !stateData.resultToSubmit || !stateData.resultToSubmit.length && 'sss-no-padding' || ''
})


// 判断是否有数据
const isHasData = computed(() => {
    return stateData.resultToSubmit && stateData.resultToSubmit.length
})

function fmtStageClass (stageId) {
    return stageId == curStage.value && 'cur-stage' || ''
}

// 选择的总数
function fmtNum (item) {
    let subjectNum = item.subjectNum || 0;
    let gradNum = item.gradeNum || 0;
    return subjectNum + gradNum;
}

// 计算学科是否全选
const isAllCheckedSubject = computed({
    get() {
        let num = stateData.stageNumMap[curStage.value] && stateData.stageNumMap[curStage.value].subjectNum;
        return num && num === stateData.stageSubjectMap[curStage.value].length || false;
    },
    set(val) {
        let num = stateData.stageNumMap[curStage.value] && stateData.stageNumMap[curStage.value].subjectNum;
        return num && num === stateData.stageSubjectMap[curStage.value].length || false;
    }
})


// 计算年级是否全选
const isAllCheckedGrade = computed({
    get() {
        let num = stateData.stageNumMap[curStage.value] && stateData.stageNumMap[curStage.value].gradeNum;
        return num && num === stateData.stageGradeMap[curStage.value].length || false;
    },
    set(val) {
        let num = stateData.stageNumMap[curStage.value] && stateData.stageNumMap[curStage.value].gradeNum;
        return num && num === stateData.stageGradeMap[curStage.value].length || false;
    }
})

watch(() => props.selectedData, (n = []) => {
    console.log(1111, n);
    stateData.initSelectData = n;
     // 组装输入框中已经选中的所有数据
    stateData.resultToSubmit = n;
    // 组装提交给后台的数据
    stateData.commitResult = n; 

    // if(!n.length) {
    //     reset();
    // }
}, {
    deep: true
})



onMounted(async () => {
    // 请求学段学科
    if(props.list && props.list.length) {
        refreshData(props.list);
    }else{
        getData();
    }
   
    isInit.value = true;
    stateData.initSelectData = props.selectedData.length && JSON.parse(JSON.stringify(props.selectedData)) || []

    await nextTick();
    // 初始化弹框宽度
    let sssList = document.querySelector('.stage-subject');
    popoverWidth.value = sssList.offsetWidth - 28;
    
    window.addEventListener('mousedown', mousedownChange, true); // 监听鼠标点击事件
})

const mousedownChange = (e) => {
    if(unref(inputStageWrapper).contains(e.target) || unref(selectStageWrapper).contains(e.target)){
         return;
    }
    closePopover();
}

onBeforeUnmount(() => {
    window.removeEventListener('mousedown', mousedownChange, true);
});

function getData () {
    // 获取学段学科年级列表
    return store.dispatch('common/getStageRefSubject').then((res) => {
        refreshData(res);
    }).catch(err => {
        console.log(err);
    }).finally(() => {
    });
}

function refreshData(res) {
    stateData.basicData = res || [];
    curStage.value = stateData.basicData.length && stateData.basicData[0] && stateData.basicData[0].stage || '';
    fmtInitData();
    fmtCheckedData();
}

// 组装所有学段与学科对象数据  stageId:[学科]
// 组装所有学段与年级对象数据  stageId:[年级]
function fmtInitData() {
    let list = stateData.basicData.length && stateData.basicData || [];
    // 学段数据
    let stageList = [];

    list.length && list.forEach(item => {
        let temp = {stage: item.stage, stageName: item.stageName}
        stageList.push(temp);
        stateData.stageNameMap[item.stage] = temp;
        stateData.stageSubjectMap[item.stage] = item.subjects || [];
        stateData.stageGradeMap[item.stage] = item.grades || [];
    })
    stateData.stages = stageList;
}

async function confirmData () {
    let stageList = stateData.stageNumMap && Object.keys(stateData.stageNumMap) || [];
    let result = [], index = -1;

    let optionStageId = optionsData.value.stageId;
    let optionStageName = optionsData.value.stageName;
    let optionSubjectId = optionsData.value.subjectId;
    let optionSubjectName= optionsData.value.subjectName;
    let optionGradeId = optionsData.value.gradeId;
    let optionGradeName = optionsData.value.gradeName;

    stageList.length && stageList.forEach((stageId) => {
        if (stateData.stageNumMap[stageId] && (stateData.stageNumMap[stageId].subjectNum || stateData.stageNumMap[stageId].gradeNum)) {
            let stageTemp = stateData.stageNameMap[stageId] || {};
            index++;
            
            // 格式化提交和输入框展示的学段数据
            let stageObj = {subjectList: [], gradeList: []};
            stageObj[optionStageId] = stageId;
            stageObj[optionStageName] = stageTemp.stageName;
            stageObj[optionStageName] = stageTemp.stageName;
            result.push(stageObj);

            let subjectList = stateData.stageSubjectMap[stageId] || [];

            subjectList.forEach(subject => {
                if (subject.checked) {
                    // 格式化提交和输入框展示的学科数据
                    let subjectObj = {};
                    subjectObj[optionSubjectId] = subject.code;
                    subjectObj[optionSubjectName] = subject.name;
                    result[index].subjectList.push(subjectObj);

                }
            });
            let gradeList = stateData.stageGradeMap[stageId] || [];
            gradeList.forEach(subject => {
                if (subject.checked) {
                    // 格式化提交和输入框展示的学科数据
                    let gradeObj = {};
                    gradeObj[optionGradeId] = subject.code;
                    gradeObj[optionGradeName] = subject.name;

                    result[index].gradeList.push(gradeObj);
                }
            });
        }
    });
    stateData.resultToSubmit = result;
    stateData.commitResult = result;

    console.log('commitResult==', result);

    if(!isInit.value){
         emit('update:selectedData', stateData.commitResult);
    }

}

// 切换学段
function checkStage(item){
    curStage.value = item.stage;
}

// 初始化组装已经选中的数据
function fmtCheckedData () {
    let checkedList = stateData.initSelectData || [];
    // 已经选择的学段学科、学段年级数据
    let checkedSubjectMap = {};
    let checkedGradeMap = {};
    
    // 后台给的回显数据 
    let optionStageId = optionsData.value.stageId;
    let optionSubjectId = optionsData.value.subjectId;
    let optionGradeId = optionsData.value.gradeId;

    reset();

    checkedList.length && checkedList.forEach(item => {
        let subjectList = item.subjectList || [];
        let tempStageId = item[optionStageId];
        stateData.stageNumMap[item[optionStageId]] = { subjectNum: 0, gradeNum: 0};
        subjectList.length && subjectList.forEach(subItem => {
            let mainId = `${tempStageId}-${subItem[optionSubjectId]}`;
            checkedSubjectMap[mainId] = subItem;
        })
        let gradeList = item.gradeList || [];
        gradeList.length && gradeList.forEach(subItem => {
            let mainId = `${tempStageId}-${subItem[optionGradeId]}`;
            checkedGradeMap[mainId] = subItem;
        })
    });
    // 将复选框勾选
    checkedList.length && checkedList.forEach(item => {
        let tempStageId = item[optionStageId];
        // 公共的初始化学科学段年级数据
        let subjectList = stateData.stageSubjectMap[item[optionStageId]] || [];
        subjectList.length && subjectList.forEach(subjectItem => {
            let mainId = `${tempStageId}-${subjectItem.code}`;
            if(checkedSubjectMap[mainId]) {
                subjectItem.checked = true;
                ++stateData.stageNumMap[tempStageId].subjectNum;
            }else{
                subjectItem.checked = false; 
            }
        })

        let gradeList = stateData.stageGradeMap[item.stageId] || [];
        gradeList.length && gradeList.forEach(gradeItem => {
            let mainId = `${tempStageId}-${gradeItem.code}`;
            if(checkedGradeMap[mainId]) {
                gradeItem.checked = true;
                ++stateData.stageNumMap[tempStageId].gradeNum;
            }else{
                gradeItem.checked = false; 
            }
        })
    });
    
    // 组装输入框中已经选中的所有数据
    stateData.resultToSubmit = checkedList;
    // 组装提交给后台的数据
    stateData.commitResult = checkedList; 
}


// 点击打开对话框
function toggle () {
    isInit.value = false;
    nextTick(() => {
        let sssList = document.querySelector('.stage-subject');
        popoverWidth.value = sssList.offsetWidth - 28;
        visible.value = !visible.value;
        if(visible.value) {
            fmtCheckedData();
        }
    })
}

function close () {
    isInit.value = false;
    visible.value = false;
}

// 删除学科单个元素数据
function delSubject (stageIndex, subjectIndex, stageId, subjectId) {
    stateData.resultToSubmit[stageIndex].subjectList.splice(subjectIndex, 1);
    if (!stateData.resultToSubmit[stageIndex].subjectList.length) {
        stateData.resultToSubmit.splice(stageIndex, 1);
    }
    let subjectList = stateData.stageSubjectMap[stageId] || [];
    
    subjectList.length && subjectList.forEach(subjectItem => {
        if(subjectItem.code === subjectId) {
            subjectItem.checked = false;
            --stateData.stageNumMap[stageId].subjectNum;
        }
    })
    stateData.commitResult = deepCopy(stateData.resultToSubmit);
    console.log('commitResult==', stateData.commitResult);
    emit('update:selectedData', stateData.commitResult);
}

// 删除年级单个元素数据
function delGrade(stageIndex, subjectIndex, stageId, subjectId) {
    stateData.resultToSubmit[stageIndex].gradeList.splice(subjectIndex, 1);
    if (!stateData.resultToSubmit[stageIndex].gradeList.length) {
        stateData.resultToSubmit.splice(stageIndex, 1);
    }
    let subjectList = stateData.stageGradeMap[stageId] || [];
    
    subjectList.length && subjectList.forEach(subjectItem => {
        if(subjectItem.code === subjectId) {
            subjectItem.checked = false;
            --stateData.stageNumMap[stageId].gradeNum;
        }
    })
    stateData.commitResult = deepCopy(stateData.resultToSubmit);
    emit('update:selectedData', stateData.commitResult);
}


// 选择学科、年级数据
function changeChecked (e, subject, type) {
    subject.checked = e;
    if(stateData.stageNumMap[curStage.value] && stateData.stageNumMap[curStage.value][type]) {
            e ? ++stateData.stageNumMap[curStage.value][type] : --stateData.stageNumMap[curStage.value][type];
    }else{
        let obj = {};
        obj[type] = e ? 1 : 0;
        stateData.stageNumMap[curStage.value] = {...{}, ...stateData.stageNumMap[curStage.value], ...obj }
    }

    console.log(stateData.stageNumMap[curStage.value])
}

// 全选/全取消 学段
function selectAll (e, type) {
    if (curStage.value == 9999) {
        for (let item in stateData.stageList) {
            setStage(e, item.stage, type);
        }
    } else {
        setStage(e, curStage.value, type);
    }
}

function setStage (selected, stageId, type) {
    let list = [];
    if(type === 'subjectNum') {
        list = stateData.stageSubjectMap[stageId] || [];
    }else{
        list = stateData.stageGradeMap[stageId] || [];
    }
    list.length && list.forEach(item => {
        item.checked = selected;
    })

    if(stateData.stageNumMap[curStage.value] && stateData.stageNumMap[stageId][type]) {
        stateData.stageNumMap[stageId][type] = selected ? list.length : 0;
    }else{
        let obj = {};
        obj[type] = selected ? list.length : 0;
        stateData.stageNumMap[stageId] = {...stateData.stageNumMap[stageId], ...obj }
    }
}

function reset(){
    resetGrade();
    resetSubject();
    if(Object.keys(stateData.stageNumMap).length){
        for (const key in stateData.stageNumMap) {
            stateData.stageNumMap[key] = 0
        }
    }
    stateData.resultToSubmit = [];
    // 组装提交给后台的数据
    stateData.commitResult = [];
}

// 清空
function resetCommit() {
    reset();
    visible.value = false;
    emit('update:selectedData', stateData.commitResult);
}

// 重置学科
function resetSubject() {
    if(Object.keys(stateData.stageSubjectMap).length){
        for (const key in stateData.stageSubjectMap) {
            stateData.stageSubjectMap[key].forEach(item => (item.checked = false))
        }
    }
}

// 重置年级
function resetGrade() {
    if(Object.keys(stateData.stageGradeMap).length){
        for (const key in stateData.stageGradeMap) {
            stateData.stageGradeMap[key].forEach(item => (item.checked = false))
        }
    }
}






function confirm () {
    confirmData();
    toggle();
}

// 关闭对话框
function closePopover(){
    visible.value = false;
}

</script>

<style lang="scss">
.subject{
    .el-checkbox__label{
        height: 20px;
        font-size: 14px;
        font-family: PingFangSC-Regular, PingFang SC;
        font-weight: 400;
        color: #666666;
        line-height: 20px;
    }
}
</style>

<style lang="scss" scoped>
$primaryColor: var(--color-primary);
$primaryOpacityColor1: #EDF4FF;
$borderHoverColor: var(--el-border-color-hover);
$placeholderColor: var(--el-text-color-placeholder);

.sss {
    min-height: 30px;
    height: auto;
    width: 100%;
    border: 1px solid #dddee1;
    padding: 0px 0px 0px 12px;
    position: relative;
    border-radius: 4px;
    box-sizing: border-box;
    &:hover {
        border-color: $borderHoverColor;
    }
    &.sss-no-padding {
        padding: 0px 0px 0px 12px;
    }
    .placeholder {
        color: $placeholderColor;
        cursor: pointer;
        user-select: none;
    }
    .icon-clear{
        color: #B9BECE;
        font-size: 14px;
        display: inline-block;
        transition: all 0.2s;
        margin: 0px 8px;
        position: absolute;
        opacity: 0;
        cursor: pointer;
    }
    &:hover{
        .icon-clear{
            opacity: 1;
        }
    }
    .ss {
        width: calc(100% - 30px);
        color: #000000;
        line-height: 30px;
        display: inline-block;

        .ss-stage {
            display: flex;
            align-items: baseline;
            margin-bottom: 4px;
            &:last-child {
                margin-bottom: 0;
            }
        }

        .ss-stageback {
            .ss-back {
            display: flex;
            align-items: baseline;
            }
        
        }
        .ss-stagename {
            font-size: 14px;
            font-family: PingFangSC-Medium, PingFang SC;
            font-weight: 400;
            color: #535A73;
            flex: 0 0 45px;
            &.ss-bold {
                font-weight: bold;
            }
        }
        .ss-subjects {
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            min-width: 100px;
        }
        .ss-subject {
            background: #ECEFF4;
            border-radius: 4px;
            padding: 1px 6px;
            margin: 0 8px 6px 0;
            height: 20px;
            font-size: 14px;
            font-family: PingFangSC-Regular, PingFang SC;
            font-weight: 400;
            color: #535A73;
            line-height: 20px;
        }
    }
}


.stage-subject-container {
    .btns {
        border-top: 1px solid #f0f0f0;
        padding: 12px 0px 0px;
        text-align: right;
    }
    .btn{
        border-radius: 2px;
        display: inline-block;
        cursor: pointer;
        user-select: none;
        padding:4px 18px;
        font-size: 14px;
        font-family: PingFangSC-Regular, PingFang SC;
        font-weight: 400;
    }
    .btn-reset {
        border: 1px solid #DDDDDD;
        color: #666666;
        margin-right:12px;
    }
    .btn-confirm {
        border: 1px solid $primaryColor;
        color: #ffffff;
        background: $primaryColor
    }
    .sss-list-inner {
        display: flex;
        align-items: stretch;
    }
    .stages {
        flex: 0 0 90px;
        padding-right: 11px;
        border-right: 1px solid #eeeeee;
        overflow-y: auto;
    }

    .stage {
        height: 28px;
        width: 100%;
        line-height: 28px;
        color: #000000;
        cursor: pointer;
        user-select: none;
        padding: 0 8px;
        box-sizing: border-box;
        margin-bottom: 10px;
        font-size: 14px;
        font-family: PingFangSC-Regular, PingFang SC;
        position: relative;
        &.cur-stage {
            color: $primaryColor;
            position: relative;
            background: $primaryOpacityColor1;
            border-radius:4px;
            color:$primaryColor;
        }
    }
    .subjects {
        padding: 4px 4px 0 16px;
        overflow-y: auto;
    }
    .subject {
        display: inline-block;
        margin-right: 16px;
        height: 32px;
        &.mtop {
            margin-top: 20px;
        }
    }
    .stage-name {
        display: inline-block;
        line-height: 28px;
    }
    .selected-num {
        font-size: 10px;
        color: #fff;
        background: $primaryColor;
        display: inline-block;
        padding: 0px 5px;
        height: 14px;
        line-height: 14px;
        text-align: center;
        border-radius: 14px;
        margin-left:4px;
    }
}

.stage-icon-guanbi {
    background: url(./assets/close.png) no-repeat;
    width: 10px;
    height: 10px;
    background-size: contain;
    display: inline-block;
    cursor: pointer;
}
.stage-icon-clear {
    background: url(./assets/clear.png) no-repeat;
    width: 16px;
    height: 16px;
    background-size: contain;
    display: inline-block;
    cursor: pointer;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
}
</style>